<?php

namespace App\Http\Controllers\Admin;

use App\Http\Exports\OrderExport;
use App\Http\Forms\OrderForm;
use App\Library\OSS;
use App\Modules\Good\Models\Good;
use App\Modules\Good\Models\GoodSpec;
use App\Modules\Order\Models\ChangeOrderPrice;
use App\Modules\Order\Models\Order;
use App\Modules\Package\Manager;
use App\Modules\Package\Models\GoodPackage;
use App\Modules\Package\Models\PackageAttr;
use App\Modules\Package\Models\PackageAttrValue;
use App\Modules\Package\Models\PackageSpec;
use App\Modules\Rebate\Jobs\RebateJob;
use App\Modules\Shop\Shop;
use App\Modules\User\Models\Admin;
use App\Modules\User\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Log;
use Ramsey\Uuid\Uuid;
use Silber\Bouncer\BouncerFacade;

class OrderController extends Controller
{
    public function detail($id)
    {
        $order = Order::query()->find($id);
        if ($order->type == Order::TYPE_PACKAGE) {
            return redirect()->route('admin.order.package_index', ['order_id' => $id]);
        } else {
            return redirect()->route('admin.order.good_index', ['order_id' => $id]);
        }
    }

    /**
     * 搜索门店
     */
    public function searchShops(Request $request){
        $this->checkAuth("merchant_staff_order", "package-order", "goods-order");
        $term           = $request->input('term');
        $is_photography = $request->input('is_photography', '');
        $query          = Shop::query()->where('is_photography', $is_photography);

        $query->where('status', 'open');
        if (!empty($term)) {
            $query->where('name', 'like', "%".$term."%");
        }

        if ($this->authUser->is_merchant_staff == Admin::MERCHANT_AUTH) {
            $query->whereIn('id', json_decode($this->authUser->shop_id, true));
        }
        
        $re = $query
            ->get()
            ->pluck('name', 'id')
            ->all();
        
        return $re;
    }

    public function packageIndex(Request $request)
    {
        $this->checkAuth("merchant_staff_order", "package-order");
        $status = $request->input('status');
        $orderId = $request->input('order_id');
        $mobile = $request->input('mobile');
        $name = $request->input('name');
        $referrerId = $request->input('referrer_id');
        $referrerName = $request->input('referrer_name');
        $merchant = $request->input('merchant');
        if ($this->authUser->is_merchant_staff == Admin::MERCHANT_AUTH) {
            // $allShop = Shop::query()
            //     ->whereIn('id', json_decode($this->authUser->shop_id, true))
            //     ->where('is_photography', 1)
            //     ->get();
            $merchant = 1;
        } else {
            // $allShop = Shop::query()
            //     ->where('is_photography', 1)
            //     ->where('status', Shop::STATUS_OPEN)
            //     ->get();
        }
//        else{
        $shopId = $request->input('shop_id', '');
        $shopName = $shopId ? Shop::query()->where('id', $shopId)->first('name')->name : '';
//        }
        $start = $request->input('start');
        $end = $request->input('end');
        $isPrepay = $request->input('is_prepay');
//        $isFinish = $request->input('is_finish', 0);
        $export = $request->input('export', 0);

        $query = Order::query()
            ->join('users', 'users.id', '=', 'orders.user_id')
            ->leftJoin('users as r', 'r.id', '=', 'orders.referrer_id')
            ->where('orders.type', Order::TYPE_PACKAGE)
//            ->where('is_finish', $isFinish)
            ->orderBy('orders.created_at', 'desc');
        if (!empty($shopId)) {
            $query->where('orders.shop_id', $shopId);
        }
        if (!empty($merchant)) {
            $query->whereIn('orders.shop_id', json_decode($this->authUser->shop_id, true));
        }


        if ($isPrepay != null) {
            $query->where('orders.is_prepay', $isPrepay);
        }
        if (!empty($start)) {
            $query->where('orders.created_at', '>', $start);
        }
        if (!empty($end)) {
            $query->where('orders.created_at', '<', Carbon::parse($end)->addDay()->toDateString());
        }
        if (!empty($orderId)) {
            $query->where('orders.id', $orderId);
        }
        if (!empty($mobile)) {
            $query->where('orders.mobile', "like", "%" . $mobile . "%");
        }
//        if (!empty($status) && $status != "") {
//            $query->where('orders.status', $status);
//        }
        if (!empty($referrerId)) {
            $query->where('orders.referrer_id', $referrerId);
        }
        if (!empty($name)) {
            $query->where('orders.name', 'like', '%' . $name . "%");
        }
        if (!empty($referrerName)) {
            $query->where('r.name', 'like', '%' . $referrerName . '%');
        }
        if ($export) {
            $data = $query
                ->select('orders.*', 'users.nickname', 'users.avatar', 'r.name as referrer_name')
                ->limit(10000)
                ->get()
                ->map(function ($item) {
                    $spec = "";
                    foreach ($item->detail['spec'] as $value) {
                        $spec .= $value['attr'] . ":" . $value['attr_value'] . " *" . $value['number'] . "\n";
                    }
                    return [
                        $item->id, $item->created_at, $item->price, $item->name,
                        $item->mobile, $item->referrer_name, Order::$statusShow[$item->status],
                        $spec,
                        $item->is_prepay ? "全款订单" : ($item->final_payment ? "已收尾款" : "未收尾款"),
                    ];
                });
            return (new OrderExport("订单.xlsx", $data->all()))->downLoad();
        }
        $count = $query->count();//订单数量
        $original_price = $query->sum('original_price') / 100;//订单价格
        $we_chat_pay = $query->sum('we_chat_pay') / 100;//微信支付
        $coupon_pay = $query->sum('coupon_pay') / 100;//优惠券
        $refund_fee = $query->sum('refund_fee') / 100;//退款金额

        $data = $query
            ->select('orders.*', 'users.nickname', 'users.avatar', 'r.name as referrer_name')
            ->paginate(20)
            ->appends($request->all());
//        $referrer = User::query()->whereIn('id', $data->pluck('referrer_id')->all())->get()->keyBy('id');
        foreach ($data as $item) {
            $spec = "";
            foreach ($item->detail['spec'] as $value) {
                $spec .= $value['attr'] . ":" . $value['attr_value'] . " *" . $value['number'] . "<br />";
            }
            $item->spec = $spec;
            if (!empty($item->bill)) {
                $bill = [];
                foreach ($item->bill as $item2) {
                    $bill[] = OSS::instance()->getUrl($item2);
                }
                $item->bill = implode(";", $bill);
            }
        }

        $sidebar = 'package';
        return view('order.index', compact('count', 'original_price', 'we_chat_pay', 'coupon_pay', 'refund_fee', 'isFinish', 'isPrepay', 'start', 'end', 'allShop', 'shopId', 'shopName', 'data', 'sidebar', 'status', 'orderId', 'mobile', 'name', 'referrerId', 'referrerName'));
    }

    public function goodIndex(Request $request)
    {
        $this->checkAuth("merchant_staff_order", "goods-order");
        $status = $request->input('status');
        $goodsName = $request->input('goods_name');
        $merchant = $request->input('merchant');
        if ($this->authUser->is_merchant_staff == Admin::MERCHANT_AUTH) {
            $allShop = Shop::query()
                ->whereIn('id', json_decode($this->authUser->shop_id, true))
                ->where('is_photography', 0)
                ->get();
            $merchant = 1;
        } else {
            $allShop = Shop::query()
                ->where('is_photography', 0)
                ->where('status', Shop::STATUS_OPEN)
                ->get();
        }
        $shopId = $request->input('shop_id', '');
        $shopName = $shopId ? Shop::query()->where('id', $shopId)->first('name')->name : '';
        $orderId = $request->input('order_id');
        $delivery = $request->input('delivery');
        $name = $request->input('name');
        $mobile = $request->input('mobile');
        $referrerId = $request->input('referrer_id');
        $referrerName = $request->input('referrer_name');
        $start = $request->input('start');
        $end = $request->input('end');
        $isPrepay = $request->input('is_prepay');
//        $isFinish = $request->input('is_finish', 0);
        $export = $request->input('export', 0);
        $query = Order::query()
            ->join('users', 'users.id', '=', 'orders.user_id')
            ->leftJoin('users as r', 'r.id', '=', 'orders.referrer_id')
            ->where('orders.type', Order::TYPE_GOOD)
//            ->where('is_finish', $isFinish)
            ->orderBy('orders.created_at', 'desc');

        if (!empty($shopId)) {
            $query->where('orders.shop_id', $shopId);
        }

        if (!empty($merchant)) {
            $query->whereIn('orders.shop_id', json_decode($this->authUser->shop_id, true));
        }

        if (!empty($isPrepay)) {
            $query->where('is_prepay', $isPrepay);
        }
        if (!empty($start)) {
            $query->where('orders.created_at', '>', $start);
        }
        if (!empty($end)) {
            $query->where('orders.created_at', '<', Carbon::parse($end)->addDay()->toDateString());
        }
        if (!empty($orderId)) {
            $query->where('orders.id', $orderId);
        }
        if ($delivery != "") {
            $query->where('orders.delivery', $delivery);
        }
        if (!empty($goodsName)) {
            $query->where('orders.title', 'like', "%" . $goodsName . "%");
        }

        if (!empty($status)) {
            switch ($status) {
                case "pending":
                    $query->where('orders.status', Order::STATUS_INIT);
                    break;
                case "prepaid":
                    $query->where('orders.is_prepay', 1)
                        ->where('orders.status', Order::STATUS_PAID)
                        ->where('final_payment', 0);
                    break;
                case "paid":
                    $query->where('orders.status', Order::STATUS_PAID)
                        ->whereRaw("if(is_prepay = 1, final_payment = 1, '')")
                        ->where('is_finish', 0);
                    break;
                case "need_comment":
                    $query
                        ->where('orders.status', Order::STATUS_PAID)
                        ->where('orders.is_finish', 1)
                        ->where('is_comment', 0);
                    break;
                case "refund":
                    $query->where('orders.status', Order::STATUS_REFUND);
                    break;
                case "close":
                    $query->where('orders.status', Order::STATUS_CLOSE);
                    break;
            }
        }
        if (!empty($mobile)) {
            $query->where('orders.mobile', "like", "%" . $mobile . "%");
        }
        if (!empty($name)) {
            $query->where('orders.name', 'like', '%' . $name . "%");
        }
        if (!empty($referrerId)) {
            $query->where('orders.referrer_id', $referrerId);
        }
        if (!empty($referrerName)) {
            $query->where('r.name', 'like', '%' . $referrerName . '%');
        }

        if ($export) {
            $data = $query
                ->select('orders.*', 'users.nickname', 'users.avatar', 'r.name as referrer_name')
                ->limit(10000)
                ->get()
                ->map(function ($item) {
                    $detail = "";
                    foreach ($item->detail as $value) {
                        $detail .= $value["good_name"] . "\n";
                    }
                    return [
                        $item->id, $item->created_at, $item->price, $item->name,
                        $item->mobile, $item->referrer_name, Order::$statusShow[$item->status],
                        $detail,
                        $item->is_prepay ? ($item->final_payment ? "已收尾款" : "未收尾款") : "全款订单",
                    ];
                });
            return (new OrderExport("订单.xlsx", $data->all()))->downLoad();
        }

        $count = $query->count();//订单数量
        $original_price = $query->sum('original_price') / 100;//订单价格
        $we_chat_pay = $query->sum('we_chat_pay') / 100;//微信支付
        $coupon_pay = $query->sum('coupon_pay') / 100;//优惠券
        $refund_fee = $query->sum('refund_fee') / 100;//退款金额

        $data = $query
            ->select('orders.*', 'users.nickname', 'users.avatar', 'r.name as referrer_name')
            ->paginate(10)
            ->appends($request->all());

        foreach ($data as $item) {
            if (!empty($item->bill)) {
                $bill = [];
                foreach ($item->bill as $item2) {
                    $bill[] = OSS::instance()->getUrl($item2);
                }
                $item->bill = implode(";", $bill);
            }
        }
        $personal = User::query()->whereIn('id', $data->pluck('personal_id')->all())->get()->keyBy('id');
        $sidebar = 'good';
        return view('order.good_index', compact('count', 'original_price', 'we_chat_pay', 'coupon_pay', 'refund_fee', 'isFinish', 'isPrepay', 'start', 'end', 'allShop', 'shopId', 'shopName', 'data', 'sidebar', 'status', 'orderId', 'personal', 'delivery', 'name', 'referrerId', 'mobile', 'referrerName', 'goodsName'));
    }

//    public function prepayIndex(Request $request)
//    {
//        $status = $request->input('status', [Order::STATUS_INIT, Order::STATUS_CLOSE, Order::STATUS_REFUND, Order::STATUS_PAID]);
//        $orderId = $request->input('orderId');
//        $mobile = $request->input('mobile');
//        $name = $request->input('name');
//
//        $query = Order::query()
//            ->join('users', 'users.id', '=', 'orders.user_id')
//            ->where('orders.is_prepay', 1)
//            ->orderBy('orders.created_at','desc');
//        if (!empty($orderId)) {
//            $query->where('orders.id', $orderId);
//        }
//        if (!empty($mobile)) {
//            $query->where('orders.mobile', "like", "%".$mobile."%");
//        }
//        if (!empty($status)) {
//            $query->whereIn('orders.status', $status);
//        }
//        if (!empty($name)) {
//            $query->where('users.nickname', 'like', '%'.$name."%");
//        }
//        $data = $query
//            ->select('orders.*', 'users.nickname', 'users.avatar')
//            ->paginate(20);
//        $referrer = User::query()->whereIn('id', $data->pluck('referrer_id')->all())->get()->keyBy('id');
//        foreach ($data as $item) {
//            $spec = "";
//            foreach ($item->detail['spec'] as $value) {
//                $spec .= $value['attr'].":".$value['attr_value']."\n";
//            }
//            $item->spec = $spec;
//        }
//        $sidebar = 'prepay';
//        return view('order.prepay_index', compact('data', 'sidebar', 'status', 'orderId', 'referrer', 'mobile', 'name'));
//    }

    public function refund($id, Request $request)
    {
        $this->checkAuth("merchant_staff_order_refund", ['package-order-refund', 'goods-order-refund']);
        $money = $request->input('money');
        $reason = $request->input('reason');
        $money = bcmul($money, 100, 0);
        /** @var Order $order */
        $order = Order::query()
            ->where('id', $id)
            ->where('status', Order::STATUS_PAID)
            ->first();
        if (is_null($order)) {
            return redirect()->back()->withErrors('订单为不可退款状态');
        }
        try {
            $order->refund($money, $reason);
        } catch (\Throwable $e) {
            return redirect()->back()->withErrors($e->getMessage());
        }

        return redirect()->back();
    }

    public function delOrder($id)
    {
        $this->checkAuth("merchant_staff_order_change", ['package-order-change', 'goods-order-change']);
        Order::query()
            ->where('id', $id)
            ->where('status', Order::STATUS_CLOSE)
            ->delete();
        return redirect()->back();
    }

    public function create()
    {
        $this->checkAuth("merchant_staff_order_create", "order-create");
        $authUser = Auth::user();
        $typeData = [
            Order::TYPE_PACKAGE => "套系商品",
            Order::TYPE_GOOD => "普通商品",
        ];
        $shop_id = "";
        if ($authUser->is_merchant_staff == Admin::MERCHANT_AUTH) { //商家职员
            $shop = Shop::query()->where("id", $authUser->shop_id)->first();
            $shop_id = $shop->id;
            if ($shop->is_photography == 1) {//摄影馆
                $typeData = [
                    Order::TYPE_PACKAGE => "套系商品",
                ];
            } else {
                $typeData = [
                    Order::TYPE_GOOD => "普通商品",
                ];
            }
        }
        $form = $this->form(OrderForm::class, [
            'method' => 'POST',
            'url' => route('admin.order.select.spec'),
            'model' => ['shop_id' => $shop_id],
        ], [
            'typeData' => $typeData,
            'shop_id' => $shop_id
        ]);
        $sidebar = 'create';

        return view('order.form', compact('form', 'sidebar'));
    }

    public function selectSpec()
    {
        $this->checkAuth("merchant_staff_order_create", "order-create");
        $form = $this->form(OrderForm::class);
        if (!$form->isValid()) {
            return redirect()->back()->withErrors($form->getErrors())->withInput();
        }
        $formData = $form->getFieldValues();

        $user = User::query()->find($formData['user_id']);
        $referrer = "无";
        if (!empty($user->referrer_id)) {
            $referrer = User::query()->find($user->referrer_id)->nickname;
        }

        $sidebar = 'create';
        if ($formData['type'] == Order::TYPE_PACKAGE) {
            $package = GoodPackage::query()->find($formData['link_id']);
            $default = [];
            foreach ($package->service as $service) {
                foreach ($service['value'] as $value) {
                    $default[$value['id']] = $value;
                }
            }
            $data = PackageSpec::query()
                ->where('package_id', $formData['link_id'])
                ->get()
                ->keyBy('attr_value_id');
            $attrValue = PackageAttrValue::query()
                ->whereIn('id', $data->pluck('attr_value_id')->all())
                ->get()
                ->keyBy('id');
            $attr = PackageAttr::query()
                ->whereIn('id', $attrValue->pluck('package_attr_id')->all())
                ->get()
                ->keyBy('id');
            $attrValue = $attrValue->groupBy('package_attr_id');
            return view('order.package_spec', compact('data', 'sidebar', 'formData', 'attrValue', 'attr', 'referrer', 'default'));
        } else {
            $data = GoodSpec::query()
                ->where('good_id', $formData['link_id'])
                ->where('stock', ">", 0)
                ->get();
            return view('order.good_spec', compact('data', 'sidebar', 'formData', 'referrer'));
        }
    }

    public function storeOrder(Request $request)
    {
        $this->checkAuth("merchant_staff_order_create", "order-create");
        $data = $request->all();
        $user = User::query()->find($data['user_id']);
        $referrerId = $user->referrer_id;
        $price = $data['price'] * 100;
        if ($data['type'] == Order::TYPE_PACKAGE) {
            $param = [
                'deliver_date' => $data['deliver_date'],
                'mobile' => $data['mobile'],
                'bill' => $data['bill'] ?? null,
            ];
            $spec = [];
            foreach ($data['spec'] as $id => $item) {
                if ($item > 0) {
                    $spec[] = [
                        'id' => $id,
                        'number' => 1,
                    ];
                }
            }
            /** @var Order $order */
            $order = Manager::createOrder($user, 0, $data['link_id'], $spec, $referrerId, null, $param);
            $order->price = $price;
            $order->offline_pay = $order->getPrice();
            $order->active(0);
            return redirect()->route('admin.order.package_index');
        } elseif ($data['type'] == Order::TYPE_GOOD) {
            $good = Good::query()->find($data['link_id']);
            $param = [
                'name' => $data['name'],
                'mobile' => $data['mobile'],
                'address' => $data['address'],
                'bill' => $data['bill'] ?? null,
            ];
            $order = \App\Modules\Good\Manager::createOrder($user, [$good->shop_id => [['id' => $data['spec'], 'number' => 1]]], $referrerId, null, $param);
            $order->price = $price;
            $order->offlineActive();
            return redirect()->route('admin.order.good_index');
        }
    }

    public function store()
    {
        $this->checkAuth("merchant_staff_order_create", "order-create");
        $form = $this->form(OrderForm::class);
        if (!$form->isValid()) {
            return redirect()->back()->withErrors($form->getErrors())->withInput();
        }
        $data = $form->getFieldValues();
        return redirect()->route('admin.order.' . $data['type'] . "_index");
    }

    public function finish($id)
    {
        $this->checkAuth("merchant_staff_order_success", ['package-order-finish', 'goods-order-finish']);

        /** @var Order $order */
        $order = Order::query()->find($id);
//        if ($order->is_prepay == 1) {
//            dispatch(new RebateJob($order));
//        }

        $order->finish();
        return redirect()->back();
    }

    public function finalPayment($id)
    {
        $this->checkAuth("merchant_staff_order_closing_payment", ['package-order-finish', 'goods-order-finish']);
        /** @var Order $order */
        $order = Order::query()->find($id);
        $order->update([
            'final_payment' => 1,
        ]);
        return redirect()->back();
    }

    public function changePrice($id, Request $request)
    {
        $this->checkAuth("merchant_staff_order_change", ['package-order-change', 'goods-order-change']);

        $money = $request->input('money');
        $reason = $request->input('reason');
        $user = Auth::user();

        $money *= 100;
        DB::beginTransaction();
        $order = Order::query()
            ->where('id', $id)
            ->where('status', Order::STATUS_INIT)
            ->lockForUpdate()
            ->first();
        $newNo = Order::getPayNo();
        ChangeOrderPrice::query()
            ->create([
                'old_pay_no' => $order->pay_no,
                'new_pay_no' => $newNo,
                'old_price' => $order->price,
                'new_price' => $money,
                'reason' => $reason,
                'operator_id' => $user->id,
            ]);
        $order->pay_no = $newNo;
        $order->price = $money;
        $order->save();
        DB::commit();

        return redirect()->back();
    }

    /**
     * 查看订单地址信息
     */
    public function getAddress($id, Request $request)
    {

        var_dump($id);
        exit();
        $this->checkAuth("merchant_staff_order_refund", ['package-order-refund', 'goods-order-refund']);
        $money = $request->input('money');
        $reason = $request->input('reason');
        $money = bcmul($money, 100, 0);
        /** @var Order $order */
        $order = Order::query()
            ->where('id', $id)
            ->where('status', Order::STATUS_PAID)
            ->first();
        if (is_null($order)) {
            return redirect()->back()->withErrors('订单为不可退款状态');
        }
        try {
            $order->refund($money, $reason);
        } catch (\Throwable $e) {
            return redirect()->back()->withErrors($e->getMessage());
        }

        return redirect()->back();
    }
}
